package jwt

import (
	"context"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/shaj13/go-guardian/auth"
	"github.com/shaj13/go-guardian/auth/strategies/basic"
	"github.com/shaj13/go-guardian/auth/strategies/bearer"
	"github.com/shaj13/go-guardian/store"
	"net/http"
	"time"
	"zhejianglab/gin-apiserver/pkg/logger"
)

var authenticator auth.Authenticator
var cache store.Cache

func validateUser(ctx context.Context, r *http.Request,userName, password string) (auth.Info, error) {
	if userName == "admin" && password == "123456" {
		return auth.NewDefaultUser("admin", "1", nil, nil), nil
	}
	return nil, fmt.Errorf("Invalid credentials")
}
func verifyToken(ctx context.Context, r *http.Request,tokenString string) (auth.Info, error) {
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("Unexpected signing method: %v",     token.Header["alg"])
		}
		return []byte("secret"), nil
	})
	if err != nil {
		return nil, err
	}
	if _, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		user := auth.NewDefaultUser("", "", nil, nil)
		return user, nil
	}
	return nil , fmt.Errorf("Invaled token")
}

func SetupGoGuardian() {
	authenticator = auth.New()
	cache = store.NewFIFO(context.Background(), time.Minute*5)
	basicStrategy := basic.New(validateUser, cache)
	tokenStrategy := bearer.New(verifyToken, cache)
	authenticator.EnableStrategy(basic.StrategyKey, basicStrategy)
	authenticator.EnableStrategy(bearer.CachedStrategyKey,tokenStrategy)
}

func JWT() gin.HandlerFunc{
	return func(c *gin.Context) {
		logger.Log.Info("Executing Auth Middleware")
		user, err := authenticator.Authenticate(c.Request)
		if err != nil {
			code := http.StatusUnauthorized
			http.Error(c.Writer, http.StatusText(code), code)
			c.Abort()
			return
		}
		logger.Log.Info(fmt.Sprintf("User %s Authenticated\n", user.UserName()))
		c.Next()
	}
}